﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Domain.Model.Base
{
    /// <summary>
    /// Clase que encapsula la logica para la identidad de los objetos del dominio
    /// La identidad 
    /// </summary>
    public abstract class ObjectIdentity
    {
        #region Atributos privados
        /// <summary>
        /// Atributo de identidad. Para mayor flexibilidad, se define de tipo object.
        /// </summary>
        private readonly object value;

        #endregion

        #region Constructor

        /// <summary>
        /// Constructor. Recibe como parametro el atributo de identidad.
        /// </summary>
        /// <param name="identity"></param>
        protected ObjectIdentity(object identity)
        {
            if (identity == null)
            {
                throw new ArgumentNullException("identity");
            }
            this.value = identity;
        }
        protected ObjectIdentity()
        {
            
            this.value = null;
        }


        #endregion

        #region Propiedades
        /// <summary>
        /// Propiedad que permite acceder al objeto de identidad
        /// </summary>
        public object Value
        {
            get
            {
                return this.value;
            }
        }

        #endregion

        #region Operadores de igualdad y comparación

        /// <summary>
        /// Sobrecarga el metodo Equals
        /// </summary>
        /// <param name="otherIdentity"></param>
        /// <returns></returns>
        public override bool Equals(object otherIdentity)
        {
            if (otherIdentity == null || !(otherIdentity is ObjectIdentity))
            {
                return false;
            }
            return (this == (ObjectIdentity)otherIdentity);
        }


        /// <summary>
        /// Sobrecarga del operador ==
        /// </summary>
        /// <param name="identity1"></param>
        /// <param name="identity2"></param>
        /// <returns></returns>
        public static bool operator ==(ObjectIdentity identity1, ObjectIdentity identity2)
        {
            //Verdadero si las dos instancias son nulas
            if ((object)identity1 == null && (object)identity2 == null)
            {
                return true;
            }
            // Falso i una de las dos instancias es nula y la otra no
            if ((object)identity1 == null || (object)identity2 == null)
            {
                return false;
            }
            if (identity1.Value != identity2.Value)
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// Sobrecarga del operador !=
        /// </summary>
        /// <param name="identity1"></param>
        /// <param name="identity2"></param>
        /// <returns></returns>
        public static bool operator !=(ObjectIdentity identity1, ObjectIdentity identity2)
        {
            return (!(identity1 == identity2));
        }

        public override int GetHashCode()
        {
            return this.value.GetHashCode();
        }

        #endregion

    }
}
